bitkeeper revision 1.1159.48.1 (4126259181cq4hyB3cquYrgpQokAIQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 20 Aug 2004 16:23:45 +0000 (16:23 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 20 Aug 2004 16:23:45 +0000 (16:23 +0000)
Framework for grant-table implementation in Xen.

.rootkeys
xen/arch/x86/domain.c
xen/common/domain.c
xen/common/grant_table.c [new file with mode: 0644]
xen/common/kernel.c
xen/common/page_alloc.c
xen/include/asm-x86/mm.h
xen/include/xen/grant_table.h [new file with mode: 0644]
xen/include/xen/sched.h

index 6089d9aa831187d96daf291507ef009579a65ad0..90083cba2ea5512f65218df88749f9f3ecabdb0f 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
 40f2b4a27xPOh3R6zD4M_aabz-TDyg xen/common/elf.c
 3fba5b96H0khoxNiKbjdi0inpXV-Pw xen/common/event_channel.c
+41262590gGIOn-1pvF5KpUu8Wb6_JA xen/common/grant_table.c
 3ddb79bd9drcFPVxd4w2GPOIjLlXpA xen/common/kernel.c
 3e4cd9d8LAAghUY0hNIK72uc2ch_Nw xen/common/keyhandler.c
 3ddb79bduhSEZI8xa7IbGQCpap5y2A xen/common/lib.c
 3ddb79c2O729EttZTYu1c8LcsUO_GQ xen/include/xen/elf.h
 3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xen/errno.h
 3ddb79c1W0lQca8gRV7sN6j3iY4Luw xen/include/xen/event.h
+41262590CyJy4vd42dnqzsn8-eeGvw xen/include/xen/grant_table.h
 3ddb79c0GurNF9tDWqQbAwJFH8ugfA xen/include/xen/init.h
 3ddb79c1nzaWu8NoF4xCCMSFJR4MlA xen/include/xen/ioport.h
 3ddb79c2qAxCOABlkKtD8Txohe-qEw xen/include/xen/irq.h
index c95d5021c93e6d2d44aa06cdac479d7c9d32c583..7a3afdd753cbb5f7ca6045ca6303a4cc070653ad 100644 (file)
@@ -472,13 +472,19 @@ void domain_relinquish_memory(struct domain *d)
      */
     destroy_gdt(d);
 
-    /* Relinquish Xen-heap pages. Currently this can only be 'shared_info'. */
-    page = virt_to_page(d->shared_info);
-    if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
-        put_page(page);
+    /* Use a recursive lock, as we may enter 'free_domheap_page'. */
+    spin_lock_recursive(&d->page_alloc_lock);
+
+    /* Relinquish Xen-heap pages. */
+    list_for_each_safe ( ent, tmp, &d->xenpage_list )
+    {
+        page = list_entry(ent, struct pfn_info, list);
+
+        if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
+            put_page(page);
+    }
 
     /* Relinquish all pages on the domain's allocation list. */
-    spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domheap_page */
     list_for_each_safe ( ent, tmp, &d->page_list )
     {
         page = list_entry(ent, struct pfn_info, list);
@@ -507,6 +513,7 @@ void domain_relinquish_memory(struct domain *d)
         }
         while ( unlikely(y != x) );
     }
+
     spin_unlock_recursive(&d->page_alloc_lock);
 }
 
index 4ca9f581356d103eb05125fdf854e4f5d393c8d8..7f5d2bafe87fa33a8de3d4e9c3dbe72b62031bdd 100644 (file)
@@ -45,7 +45,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
 
     spin_lock_init(&d->page_alloc_lock);
     INIT_LIST_HEAD(&d->page_list);
-    d->max_pages = d->tot_pages = 0;
+    INIT_LIST_HEAD(&d->xenpage_list);
 
     /* Per-domain PCI-device list. */
     spin_lock_init(&d->pcidev_lock);
@@ -53,12 +53,13 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
 
     if ( d->domain != IDLE_DOMAIN_ID )
     {
-        if ( init_event_channels(d) != 0 )
+        if ( (init_event_channels(d) != 0) || (grant_table_create(d) != 0) )
         {
+            destroy_event_channels(d);
             free_domain_struct(d);
             return NULL;
         }
-        
+
         /* We use a large intermediate to avoid overflow in sprintf. */
         sprintf(buf, "Domain-%u", dom_id);
         strncpy(d->name, buf, MAX_DOMAIN_NAME);
@@ -256,6 +257,7 @@ void domain_destruct(struct domain *d)
     write_unlock_irqrestore(&tasklist_lock, flags);
 
     destroy_event_channels(d);
+    grant_table_destroy(d);
 
     free_perdomain_pt(d);
     free_xenheap_page((unsigned long)d->shared_info);
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
new file mode 100644 (file)
index 0000000..f1a73cb
--- /dev/null
@@ -0,0 +1,134 @@
+/******************************************************************************
+ * common/grant_table.c
+ * 
+ * Mechanism for granting foreign access to page frames, and receiving
+ * page-ownership transfers.
+ * 
+ * Copyright (c) 2004 K A Fraser
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define __GRANT_TABLE_IMPLEMENTATION__
+typedef struct grant_table grant_table_t;
+
+#include <xen/config.h>
+#include <xen/sched.h>
+#include <hypervisor-ifs/grant_table.h>
+
+/* Active grant entry - used for shadowing GTF_permit_access grants. */
+typedef struct {
+    u32           counts; /* Reference count information.   */
+    u16           next;   /* Mapping hash chain.            */
+    domid_t       domid;  /* Domain being granted access.   */
+    unsigned long frame;  /* Frame being granted.           */
+} active_grant_entry_t;
+
+/* Bitfields in active_grant_entry_t:counts. */
+ /* Grant is pinned by 'domid' for read mappings and I/O. */
+#define _GNTCNT_read_pinned  (0)
+#define GNTCNT_read_pinned   (1<<_GNTCNT_read_pinned)
+ /* Grant is pinned by 'domid' for write mappings and I/O. */
+#define _GNTCNT_write_pinned (1)
+#define GNTCNT_write_pinned  (1<<_GNTCNT_write_pinned)
+ /* Grant is pinned in IOMMU (read-only unless GNTCNT_write_pinned). */
+#define _GNTCNT_io_pinned    (2)
+#define GNTCNT_io_pinned     (1<<_GNTCNT_io_pinned)
+ /* Grant is mappable (read-only unless GNTCNT_write_pinned). */
+#define _GNTCNT_mappable     (3)
+#define GNTCNT_mappable      (1<<_GNTCNT_mappable)
+ /* Count of writable page mappings. (!GNTCNT_write_pinned => count==0). */
+#define GNTCNT_wmap_shift    (4)
+#define GNTCNT_wmap_mask     (0x3FFFU << GNTCNT_wmap_shift)
+ /* Count of read-only page mappings. */
+#define GNTCNT_rmap_shift    (18)
+#define GNTCNT_rmap_mask     (0x3FFFU << GNTCNT_rmap_shift)
+
+#define MAPHASH_SZ       (256)
+#define MAPHASH(_k)      ((_k) & (MAPHASH_SZ-1))
+#define MAPHASH_INVALID  (0xFFFFU)
+
+#define NR_GRANT_ENTRIES     (PAGE_SIZE / sizeof(grant_entry_t))
+
+/* Per-domain grant information. */
+struct grant_table {
+    /* Shared grant table (see include/hypervisor-ifs/grant_table.h). */
+    grant_entry_t        *shared;
+    /* Active grant table. */
+    active_grant_entry_t *active;
+    /* Lock protecting updates to maphash and shared grant table. */
+    spinlock_t            lock;
+    /* Hash table: frame -> active grant entry. */
+    u16                   maphash[MAPHASH_SZ];
+};
+
+int grant_table_create(struct domain *d)
+{
+    grant_table_t *t;
+    int            i;
+
+    if ( (t = xmalloc(sizeof(grant_table_t))) == NULL )
+        goto no_mem;
+
+    /* Simple stuff. */
+    t->shared = NULL;
+    t->active = NULL;
+    spin_lock_init(&t->lock);
+    for ( i = 0; i < MAPHASH_SZ; i++ )
+        t->maphash[i] = MAPHASH_INVALID;
+
+    /* Active grant-table page. */
+    if ( (t->active = xmalloc(sizeof(active_grant_entry_t) * 
+                              NR_GRANT_ENTRIES)) == NULL )
+        goto no_mem;
+
+    /* Set up shared grant-table page. */
+    if ( (t->shared = (void *)alloc_xenheap_page()) == NULL )
+        goto no_mem;
+    memset(t->shared, 0, PAGE_SIZE);
+    SHARE_PFN_WITH_DOMAIN(virt_to_page(t->shared), d);
+
+    /* Okay, install the structure. */
+    d->grant_table = t;
+    return 0;
+
+ no_mem:
+    if ( t != NULL )
+    {
+        if ( t->active != NULL )
+            xfree(t->active);
+        xfree(t);
+    }
+    return -ENOMEM;
+}
+
+void grant_table_destroy(struct domain *d)
+{
+    grant_table_t *t;
+
+    if ( (t = d->grant_table) != NULL )
+    {
+        /* Free memory relating to this grant table. */
+        d->grant_table = NULL;
+        free_xenheap_page((unsigned long)t->shared);
+        xfree(t->active);
+        xfree(t);
+    }
+}
+
+void grant_table_init(void)
+{
+    /* Nothing. */
+}
index 707cede7f193bfe8c39109b7395f94d7b18aff96..6c0775c9d2d5f1e16e6ec035e96fbeacf028977f 100644 (file)
@@ -304,6 +304,8 @@ void cmain(multiboot_info_t *mbi)
 
     start_of_day();
 
+    grant_table_init();
+
     /* Create initial domain 0. */
     new_dom = do_createdomain(0, 0);
     if ( new_dom == NULL )
index 323ecd244e1e810ad576f1e2984d1859fc248de4..52da9c042bdcf2a7a4da6388467f2377313aaf73 100644 (file)
@@ -418,6 +418,8 @@ void free_domheap_pages(struct pfn_info *pg, int order)
     if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
     {
         spin_lock_recursive(&d->page_alloc_lock);
+        for ( i = 0; i < (1 << order); i++ )
+            list_del(&pg[i].list);
         d->xenheap_pages -= 1 << order;
         drop_dom_ref = (d->xenheap_pages == 0);
         spin_unlock_recursive(&d->page_alloc_lock);
index a2fc40e0b32bc0c7ad6ce584c7106bc1ac0a48a6..5cd3c01ae6d0d2e0b3d8a5d4ebde913f4d6e3454 100644 (file)
@@ -109,6 +109,7 @@ struct pfn_info
         (_pfn)->u.inuse.count_info = PGC_allocated | 1;                     \
         if ( unlikely((_dom)->xenheap_pages++ == 0) )                       \
             get_knownalive_domain(_dom);                                    \
+        list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list);                \
         spin_unlock(&(_dom)->page_alloc_lock);                              \
     } while ( 0 )
 
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
new file mode 100644 (file)
index 0000000..92a81de
--- /dev/null
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * include/xen/grant_table.h
+ * 
+ * Mechanism for granting foreign access to page frames, and receiving
+ * page-ownership transfers.
+ * 
+ * Copyright (c) 2004 K A Fraser
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __XEN_GRANT_H__
+#define __XEN_GRANT_H__
+
+#ifndef __GRANT_TABLE_IMPLEMENTATION__
+typedef void grant_table_t;
+#endif
+
+/* Start-of-day system initialisation. */
+void grant_table_init(void);
+
+/* Create/destroy per-domain grant table context. */
+int  grant_table_create(struct domain *d);
+void grant_table_destroy(struct domain *d);
+
+#endif /* __XEN_GRANT_H__ */
index af74cf5380100dd69370a698ffc788c8d877d3e4..dfea4b7509dd9d7026f54dea9383a20f053730ee 100644 (file)
@@ -4,16 +4,13 @@
 #include <xen/config.h>
 #include <xen/types.h>
 #include <xen/spinlock.h>
-#ifdef LINUX_2_6
-#include <linux/thread_info.h>
-#endif
 #include <asm/ptrace.h>
 #include <xen/smp.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <hypervisor-ifs/hypervisor-if.h>
 #include <hypervisor-ifs/dom0_ops.h>
-
+#include <xen/grant_table.h>
 #include <xen/list.h>
 #include <xen/time.h>
 #include <xen/ac_timer.h>
@@ -95,6 +92,7 @@ struct domain
 
     spinlock_t       page_alloc_lock; /* protects all the following fields  */
     struct list_head page_list;       /* linked list, of size tot_pages     */
+    struct list_head xenpage_list;    /* linked list, of size xenheap_pages */
     unsigned int     tot_pages;       /* number of pages currently possesed */
     unsigned int     max_pages;       /* maximum value for tot_pages        */
     unsigned int     xenheap_pages;   /* # pages allocated from Xen heap    */
@@ -121,6 +119,8 @@ struct domain
     unsigned int     max_event_channel;
     spinlock_t       event_channel_lock;
 
+    grant_table_t *grant_table;
+
     /*
      * Interrupt to event-channel mappings. Updates should be protected by the 
      * domain's event-channel spinlock. Read accesses can also synchronise on